package org.budo.aliyun.sdk.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.budo.aliyun.sdk.BudoAliyunEssSdk;
import org.budo.aliyun.sdk.BudoAliyunRegion;
import org.budo.aliyun.sdk.impl.response.DescribeScalingActivitiesResponse;
import org.budo.aliyun.sdk.impl.response.DescribeScalingInstancesResponse;
import org.budo.aliyun.sdk.impl.response.DescribeScalingInstancesResponse.ScalingInstance;
import org.budo.aliyun.sdk.impl.response.ExecuteScalingRuleResponse;
import org.budo.aliyun.sdk.impl.response.RemoveInstancesResponse;
import org.budo.support.assertion.Assert;
import org.budo.support.http.client.Response;
import org.budo.support.lang.util.StringUtil;
import org.budo.support.slf4j.Slf4j;
import org.slf4j.Logger;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

/**
 * 弹性伸缩
 * 
 * @author lmw
 */
public class BudoAliyunEssSdkImpl extends AbstractBudoAliyunEssSdk implements BudoAliyunEssSdk {
    private static final Logger log = Slf4j.getLogger();

    @Override
    public RemoveInstancesResponse removeInstances(String scalingGroupId, String instanceId) {
        Assert.notEmpty(scalingGroupId, "scalingGroupId can not be empty");
        Assert.notEmpty(instanceId, "instanceId can not be empty");

        Map<String, Object> parameters = this.commonParameters();
        parameters.put("Action", ACTION_REMOVE_INSTANCES);

        parameters.put("ScalingGroupId", scalingGroupId);
        parameters.put("InstanceId.1", instanceId);

        Response response = this.doRequest(parameters);
        log.info("removeInstances, response=" + (null == response ? response : response.toSimpleString()));

        JSONObject responseJsonObject = this.responseJsonObject(response);
        RemoveInstancesResponse removeInstancesResponse = new RemoveInstancesResponse();
        removeInstancesResponse.setScalingActivityId(responseJsonObject.getString("ScalingActivityId"));
        return removeInstancesResponse;
    }

    @Override
    public DescribeScalingActivitiesResponse describeScalingActivities(String regionId, String scalingGroupId) {
        Assert.notEmpty(regionId, "regionId can not be empty 3");

        Map<String, Object> parameters = this.commonParameters();
        parameters.put("Action", ACTION_DESCRIBE_SCALING_ACTIVITIES);

        parameters.put("RegionId", regionId);
        if (!StringUtil.isEmpty(scalingGroupId)) {
            parameters.put("ScalingGroupId", scalingGroupId);
        }

        Response response = this.doRequest(parameters);
        log.info("describeScalingActivities, response=" + (null == response ? response : response.toSimpleString()));

        DescribeScalingActivitiesResponse describeScalingActivitiesResponse = new DescribeScalingActivitiesResponse();
        return describeScalingActivitiesResponse;
    }

    @Override
    public ExecuteScalingRuleResponse executeScalingRule(String scalingRuleAri, String clientToken) {
        Assert.notEmpty(scalingRuleAri, "scalingRuleAri can not be empty");
        Assert.notEmpty(clientToken, "clientToken can not be empty");

        log.info("#105 executeScalingRule 1, scalingRuleAri=" + scalingRuleAri + ", clientToken=" + clientToken);

        Map<String, Object> parameters = this.commonParameters();
        parameters.put("Action", ACTION_EXECUTE_SCALING_RULE);

        parameters.put("ScalingRuleAri", scalingRuleAri);
        parameters.put("ClientToken", clientToken);

        Response response = this.doRequest(parameters);
        JSONObject jsonObject = this.responseJsonObject(response);

        String scalingActivityId = jsonObject.getString("ScalingActivityId");
        if (StringUtil.isEmpty(scalingActivityId)) {
            throw new RuntimeException("#118 executeScalingRule error" + ", responseBody=" + response.getBody() + ", response=" + response);
        }

        ExecuteScalingRuleResponse executeScalingRuleResponse = new ExecuteScalingRuleResponse();
        executeScalingRuleResponse.setRequestId(jsonObject.getString("RequestId"));
        executeScalingRuleResponse.setScalingActivityId(scalingActivityId);
        return executeScalingRuleResponse;
    }

    @Override
    public DescribeScalingInstancesResponse describeScalingInstances(BudoAliyunRegion region, String scalingGroupId) {
        Assert.notNull(region, "region can not be null 2");
        Assert.notEmpty(scalingGroupId, "scalingGroupId can not be empty");

        Map<String, Object> parameters = this.commonParameters();
        parameters.put("Action", ACTION_DESCRIBE_SCALING_INSTANCES);

        parameters.put("RegionId", region.getId());
        if (!StringUtil.isEmpty(scalingGroupId)) {
            parameters.put("ScalingGroupId", scalingGroupId);
        }

        Response response = this.doRequest(parameters);
        log.info("describeScalingInstances, response=" + (null == response ? response : response.toSimpleString()));
        DescribeScalingInstancesResponse describeScalingInstancesResponse = new DescribeScalingInstancesResponse();

        List<ScalingInstance> scalingInstances = new ArrayList<ScalingInstance>();

        JSONObject jsonObject = this.responseJsonObject(response);
        JSONObject scalingInstancesJsonObject = jsonObject.getJSONObject("ScalingInstances");
        if (null == scalingInstancesJsonObject) {
            throw new RuntimeException("no ScalingInstances, response=" + (null == response ? response : response.toSimpleString()));
        }

        JSONArray scalingInstanceJsonArray = scalingInstancesJsonObject.getJSONArray("ScalingInstance");

        for (Object each : scalingInstanceJsonArray) {
            JSONObject scalingInstanceJsonObject = (JSONObject) each;
            ScalingInstance scalingInstance = new ScalingInstance();
            scalingInstance.setScalingConfigurationId(scalingInstanceJsonObject.getString("ScalingConfigurationId"));
            scalingInstance.setLoadBalancerWeight(scalingInstanceJsonObject.getInteger("LoadBalancerWeight"));
            scalingInstance.setCreationTime(scalingInstanceJsonObject.getString("CreationTime"));
            scalingInstance.setCreationType(scalingInstanceJsonObject.getString("CreationType"));
            scalingInstance.setHealthStatus(scalingInstanceJsonObject.getString("HealthStatus"));
            scalingInstance.setScalingGroupId(scalingInstanceJsonObject.getString("ScalingGroupId"));
            scalingInstance.setInstanceId(scalingInstanceJsonObject.getString("InstanceId"));
            scalingInstance.setLifecycleState(scalingInstanceJsonObject.getString("LifecycleState"));

            scalingInstances.add(scalingInstance);
        }

        describeScalingInstancesResponse.setScalingInstances(scalingInstances);

        return describeScalingInstancesResponse;
    }
}